//
//  ChatVC.swift
//  YueChat
//
//  Created by IMac on 2024/9/23.
//

import UIKit
import MobileCoreServices
import UniformTypeIdentifiers
import Kingfisher
import ZLPhotoBrowser
import PopMenu

class UiNotifyInfo {
    

}
class UiMessageInfo {
    var showTime = false
    var msgCellHeight = 0
    var msgCellWidth = 0
    var msgDigestHeight = 0
    var message:DMCCMessage
   
    init(_ m:DMCCMessage){
        message = m
    }
    func digest()->String{
        return ""
    }
//    func getFrom()->String{
//        return if message.direction == OsnMessageDirection.Receive{
//            message.target
//        }else{
//            message.originalUser
//        }
//    }

    
    
}

class ChatVC: BaseVC,SendViewDelegate,ChatCellDelegate,LGAudioPlayerDelegate,UIDocumentPickerDelegate,UIDocumentInteractionControllerDelegate {
   
    


    var conversation = DMCCConversation()
    
    var myInfo = DMCCUser()
    var chatType = Int()
    var isLoadMore = 0
    var isOneceLoad = 0
    var isRefrash = Bool()
    var isShowFooter = Bool()
    var isMulSelect = Bool()
    var keyHeight = Float()
    var textHeight = Float()
    var cellContentDict = NSMutableDictionary()//[Int:Any]()
    var upLongArray =  [String]()
    var sendNoticeArray =  [String]()
    var timeInterval:String = String()
    var lock = NSLock() // 假设 Object 是一个具体的类
    var replyMsg : DMCCMessage?
    var searchMsg : DMCCMessage?
    var lastDateInterval = Int64(0)
    var msgShowTimeCount = Int(0)
    var doVC:UIDocumentInteractionController?
    
    
//    lazy var audioView: FWAudioView = {
//        let audioView =  Bundle.main.loadNibNamed("FWAudioView", owner: self, options: nil)?.first as? FWAudioView
//        audioView?.AudioViewStartBlock = AudioViewStartBlock
//        audioView?.AudioViewStopBlock = AudioViewStopBlock
//        audioView?.audioCompletionBlock = audioCompletionBlock
//        self.view.addSubview(audioView!)
//        return audioView!
//    }()
    
    lazy var audioView: AudioView = {
        let audioView =  Bundle.main.loadNibNamed("AudioView", owner: self, options: nil)?.first as? AudioView
        audioView?.audioBlock = audioCompletionBlock
        self.view.addSubview(audioView!)
        return audioView!
    }()
    
    
    lazy var noticeView: NoticeHeadView = {
        let noticeView =  Bundle.main.loadNibNamed("NoticeHeadView", owner: self, options: nil)?.first as? NoticeHeadView
        noticeView?.noticeBlock  = noticeBlock
        self.view.addSubview(noticeView!)
        return noticeView!
    }()
    
    lazy var emoView : EmoImgView = {
        let emoView =  EmoImgView()
        emoView.emoSendBlock  = emoSendBlock
        emoView.emoClickBlock = emoClickBlock
        self.view.addSubview(emoView)
        return emoView
    }()
    
    lazy var moreView : MoreView = {
        let moreView =  MoreView()
        moreView.setType(type: self.chatType)
        moreView.moreSendBlock  = moreSendBlock
        self.view.addSubview(moreView)
        return moreView
    }()
    
    lazy var sendView: SendView = {
        let sendView =  Bundle.main.loadNibNamed("SendView", owner: self, options: nil)?.first as? SendView
        sendView?.delegate = self
        sendView?.chatType = self.chatType
        self.view.addSubview(sendView!)
        return sendView!
    }()
    
    init(conversation: DMCCConversation = DMCCConversation()) {
        super.init(nibName: nil, bundle: nil)
        self.conversation = conversation
    }
    
    init(conversation: DMCCConversation = DMCCConversation(),msg:DMCCMessage) {
        super.init(nibName: nil, bundle: nil)
        self.searchMsg = msg
        self.conversation = conversation
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        getMyUser()
        self.chatType = Int(self.conversation.type.rawValue)
        
        if (self.conversation.draft.count > 0) {
            self.sendView.textView.text = self.conversation.draft
        }
        
        if self.chatType == 0 { //单聊
            self.timeInterval = "0";
            self.title = user.getAlias()
        }else if self.chatType == 1{ //群聊
//            self.timeInterval = group.getAttributeText("TimeInterval")
            self.timeInterval = "0"
            self.title = "\(group.name)(\(group.memberCount))"
            self.groupUpdata()
            
        }else{

                        
        }
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppearance), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDismiss), name: UIResponder.keyboardWillHideNotification, object: nil)
        
        
        
        if(self.sendView.frame.origin.y < kScreenHeight - self.sendView.frame.size.height - iPhoneXTopHeight && self.sendView.frame.origin.y != 0 && self.moreView.isHidden && self.emoView.isHidden) {
            recoverAllView()
        }

    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
       
        setup()
        registerNotification()
    }
    
    func getMyUser() {
        
        let userInfo = gosnUser.getUserInfoDefault(gosnUser.myId())
        self.myInfo = userInfo
        self.isOneceLoad = 0
        self.loadDBMessage()
    }

    
    // MARK: - 数据处理
    func loadDBMessage() {
        // 控制是否首次加载
        let isOnceLoad = self.isOneceLoad == 0 && self.isLoadMore > 0
        if isOnceLoad { return }

        var timestamp: Int64 = 0
        if !self.dataSource.isEmpty {
            let msg = self.dataSource.first as! DMCCMessage
            timestamp = msg.timestamp
        }

//        let ws = WS()  假设WS是一个初始化器或者返回一个对象的函数
        print("时间：\(timestamp)")
        let messageList = gosnMessage.getMessageList(conversation.targetId, timestamp, 30) //.getMessages(conversation, from: timestamp, count: 50)

        
        let index = self.dataSource.count > 0 ? self.dataSource.count : 1

        dataSource = Array(messageList.reversed()) + dataSource
        if dataSource.count > 0 {
            let lastMsg = dataSource.last as! DMCCMessage
            
            lastDateInterval = lastMsg.timestamp
        }
        msgShowTimeCount = 0
        
        GK_main_async_safe { [weak self] in
            guard let self = self else { return}
            self.tableView.mj_header!.endRefreshing()
            self.tableView.reloadData()

            guard !self.dataSource.isEmpty else { return }

            if self.searchMsg != nil {
                self.goSearchMsg()
                self.searchMsg = nil
            }else if self.isLoadMore == 0 {
                let indexPath = IndexPath(row: self.dataSource.count - 1, section: 0)
                self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
            }  else {
                let indexPath = IndexPath(row: self.dataSource.count - index, section: 0)
                self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
            }

            self.isLoadMore += 1
            self.isOneceLoad += 1
        }
    }

    
    @objc func loadMoreFooterData() {
        var timestamp: Int64 = 0
        if !self.dataSource.isEmpty {
            let msg = self.dataSource.last as! DMCCMessage
            timestamp = Int64(msg.timestamp)
        }

        let messageList = gosnMessage.getMessageList(conversation.targetId, timestamp, 30)

        guard !messageList.isEmpty else {
            self.tableView.mj_footer!.endRefreshing()
            return
        }

        self.dataSource.append(contentsOf: messageList)

        let index = messageList.count > 0 ? messageList.count : 1
        DispatchQueue.main.async {
            self.tableView.reloadData()
            self.tableView.mj_footer?.endRefreshing()

            guard !self.dataSource.isEmpty else { return }

            if self.isLoadMore == 0 {
                let indexPath = IndexPath(row: self.dataSource.count - 1, section: 0)
                self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
            } else {
                let indexPath = IndexPath(row: self.dataSource.count - index, section: 0)
                self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
            }
        }
    }
    
//MARK: 发送消息
    
    func sendMessage(content: OsnMessageContent?, pwd: String) {
        if content == nil {
            return
        }
        
        let time = (Int64(timeInterval)! * 1000)
        
        if time != 0 {
            let currentTime = Date.timeStamp(withDateString: Date.getCurrentTime())
            if let msg = dataSource.last {
                if ((msg as AnyObject).timestamp + Double(time)) > currentTime {
                    MHAlert.showMessage(KLocalizedString("SpeedMessageSend"))
                    return
                }
            }
        }
        
//        let updatedContent = getKeywordWithContent(content!)
//        
//        fileContentUpdate(updatedContent, pwd: pwd)
//        let service = DMCCIMService.getInstance()
        
        if (gosnConversation.getConversationInfo(conversation.targetId) == nil) {
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                geventService.post(.kUpDateConversation, "")
            }
        }
        
        Task {
            let (msg,error) = await gosnMessage.sendMessage(conversation.targetId, content!)
            
            if error == nil {
                GK_main_async_safe {[weak self] in
                    guard let self = self else { return}
                    
                    
                    
                    if msg.msgHash.count == 0{
                        return
                    }
                    
                    self.replyMsg = nil
                    self.sendNoticeArray.removeAll()
                    self.upLongArray = [String]()
                    msg.showTime = needShowTime(time: msg.timestamp)
                    self.dataSource.append(msg)
                    self.tableView.reloadData()
                    
                    if self.dataSource.isEmpty {
                        return
                    }
                    
                    refreshTableviewY(height: self.tableView.mj_h - sendView.mj_y)
                    
                    let index = IndexPath(row: self.dataSource.count - 1, section: 0)
                    self.tableView.scrollToRow(at: index, at: .bottom, animated: false)
                    
//                    let messageList = [msg]
//                    NotificationCenter.default.post(name: Notification.Name(rawValue: OsnEvent.ReceiveMessages.rawValue), object: messageList)
                    
//                    self.reloadMessage()
                }
            }
        }
        
//        service?.send(self.conversation!, content: updatedContent, pwd: pwd) { [weak self] msgHash, timestamp in
//            DispatchQueue.main.async {
//                guard let self = self else { return }
//                
//                if msgHash == nil {
//                    return
//                }
//                
//                self.reloadMessage()
//            }
//        } error: { [weak self] errorCode in
//            guard let self = self else { return }
//            
//            self.reloadMessage()
//        } sendingCB: { [weak self] msgHash, timestamp in
//            guard let self = self else { return }
//            
//            if msgHash == nil {
//                return
//            }
//            
//            self.replyMsg = nil
//            self.sendNoticeArray.removeAll()
//            self.upLongArray = [String]()
//            
//            self.dataSource.append(service!.queryMessage(msgHash) as DMCCMessage)
//            self.tableView.reloadData()
//            
//            if self.dataSource.isEmpty {
//                return
//            }
//            
//            let index = IndexPath(row: self.dataSource.count - 1, section: 0)
//            self.tableView.scrollToRow(at: index, at: .bottom, animated: false)
//            
//            let messageList = [service!.queryMessage(msgHash)]
//            NotificationCenter.default.post(name: Notification.Name(rawValue: "kReceiveMessages"), object: messageList)
//        }
    }
    
    func updateTableView(_ msg:DMCCMessage) {
        GK_main_async_safe {
            if msg.msgHash.count == 0{
                return
            }
            
            self.replyMsg = nil
            self.sendNoticeArray.removeAll()
            self.upLongArray = [String]()
            
            self.dataSource.append(msg)
            self.tableView.reloadData()
            
            if self.dataSource.isEmpty {
                return
            }
            
            let index = IndexPath(row: self.dataSource.count - 1, section: 0)
            self.tableView.scrollToRow(at: index, at: .bottom, animated: false)
        }
    }

    func fileContentUpdate(_ content: OsnMessageContent, pwd: String) {
//        if content is OsnFileMessageContent ||
//            content is OsnImageMessageContent ||
//            content is OsnVideoMessageContent ||
//            content is OsnVoiceMessageContent ||
//            content is OsnStickerMessageContent {
        if gosnContent.isMedia(content){
            
//            if let mediaMessageContent = content as? OsnMediaMessageContext {
//                let localPath = mediaMessageContent.localPath
//                let remoteUrl = FileTool.shared.uploadFile(filePath: localPath, password: pwd) { url in
//                    
//                } progress: { uploaded, total in
//                    
//                } error: { err in
//                    
//                }
//
////                uploadFile(filePath: localPath!, password: pwd, success: { link in }) { uploaded, total in }) { error_code in })
//                
//                let fileData = try? Data(contentsOf: URL(fileURLWithPath: localPath))
//                mediaMessageContent.fileSize = Int(UInt(fileData?.count ?? 0))
//                mediaMessageContent.remoteUrl = remoteUrl!
//                mediaMessageContent.decKey = pwd
//            }
        }
    }

//    func sendMessageAgain(_ message: DMCCMessage, conversation: DMCCConversation) {
//
//        let json = message.uiData
//        
//        let service = DMCCIMService.getInstance()
//        service!.sendMessageAgain((json as! NSMutableDictionary), message: message, conversation: conversation, progress: nil) { [weak self] msgHash, timestamp in
//            DispatchQueue.main.async {
//                guard let self = self else { return }
//                
//                if msgHash == nil {
//                    return
//                }
//                
//                MHAlert.dismiss()
//                self.replyMsg = nil
//                
//                if !self.sendNoticeArray.isEmpty {
//                    self.sendNoticeArray.removeAll()
//                    self.upLongArray = [String]()
//                }
//                
//                self.dataSource.append(service!.queryMessage(msgHash) as DMCCMessage)
//                self.tableView.reloadData()
//                
//                if self.dataSource.isEmpty {
//                    return
//                }
//                
//                let index = IndexPath(row: self.dataSource.count - 1, section: 0)
//                self.tableView.scrollToRow(at: index, at: .bottom, animated: false)
//            }
//        } error: { [weak self] errorCode in
//            guard let self = self else { return }
//            
//            self.reloadMessage()
//        }
//    }

    
    // 发送语音消息
    func sendAudioMessage(amrPath: String) {
        let url = URL(string: amrPath)
        var avAudioPlayer = try? AVAudioPlayer(contentsOf: url!)
        let duration = avAudioPlayer?.duration ?? 0
        
        avAudioPlayer = nil
        
        if duration < 1 {
            MHAlert.showMessage(KLocalizedString("AlertSendVoiceTime"))
            return
        }
//        let password = getRandString(withLength: 8)
//        let messageContent = gosnMessage.makeVoiceMessage(amrPath, "", password)
//        self.sendFile(contnet: messageContent,pwd: password)
        
        Task {
            let (msg, err) = await gosnMessage.sendVoiceMessage(self.conversation.targetId, amrPath)
            await MainActor.run {
                if err == nil {
                    MHAlert.dismiss()
                    self.updateTableView(msg!)
                }else{
                    MHAlert.showMessage(KLocalizedString("发送失败"))
                }
            }
        }
    }
    
    func sendImage () {//发送图片
        let imagePickerVc = TZImagePickerController(maxImagesCount: 9, delegate: nil)
        
        imagePickerVc!.modalPresentationStyle = .fullScreen
//        imagePickerVc!.preferredLanguage = OSNLanguage.getLanguage()
                
        imagePickerVc!.didFinishPickingPhotosHandle = { [weak self] photos, assets, isSelectOriginalPhoto in
            guard let self = self else {return}
            MHAlert.showLoading()

            photos?.forEach({ image in
                let uuid = UUID().uuidString
                let cacheDir = cachePath(of: self.conversation, mediaType: .image)
                // 构建图片路径
                let path = "\(cacheDir)/img\(uuid).jpg"
                
//                    let password = getRandString(withLength: 8)
                
                // 构建图片路径

                let data = image.jpegData(compressionQuality: 1)! as Data

                do {
                    try data.write(to: URL(fileURLWithPath: path))
                } catch {
                    print("Failed to create directory at path: \(path) due to error: \(error)")
                }

                Task {
                    let (msg, err) = await gosnMessage.sendImageMessage(self.conversation.targetId, path)
                    await MainActor.run {
                        if err == nil {
                            MHAlert.dismiss()
                            self.updateTableView(msg!)
                        }else{
                            MHAlert.showMessage(KLocalizedString("发送失败"))
                        }
                    }
                }
            })
            
//            assets!.forEach { asset in
//
//                let options = PHImageRequestOptions()
//                options.isSynchronous = true // 同步请求，如果你想要在主线程中使用这个路径
//                options.deliveryMode = .highQualityFormat // 高质量图片
//                let ass = asset as! PHAsset
//                // asset:PHAsset
//                // 通过asset获取图片在相册中的路径url
//                ass.requestContentEditingInput(with: PHContentEditingInputRequestOptions()) { [weak self] (contentEditingInput, info) in
//                    guard let self = self else { return}
//                    if let input = contentEditingInput {
//                        if let url = input.fullSizeImageURL {
//                            print("[FW] \(url.path)")
//                            Task {
//                                let (msg, err) = await gosnMessage.sendImageMessage(self.conversation.targetId, url.path)
//                                await MainActor.run {
//                                    GK_main_async_safe {
//                                        if err == nil {
//                                            MHAlert.dismiss()
//                                            self.updateTableView(msg!)
//                                        }else{
//                                            MHAlert.showMessage(KLocalizedString("发送失败"))
//                                        }
//                                    }
//                                }
//                            }
//                            
//                        }
//                    }
//                }
//
//            }

        }
                
        imagePickerVc!.didFinishPickingVideoHandle = { [weak self] coverImage, asset in
            guard let self = self else {return}
            MHAlert.showLoading()
            
            TZImageManager.default()!.getVideoOutputPath(with: asset) { [weak self] outputPath in
                guard let self = self else {return}
                
                let cacheDir = cachePath(of: self.conversation, mediaType: .video)
                // 构建图片路径
                let path = "\(cacheDir)/veido\(OsnUtils.getTimeStamp()).mp4"
                
                let fileURL = URL(fileURLWithPath: outputPath!)
                do {
                    let data = try Data(contentsOf: fileURL)
                    
                    do {
                        try data.write(to: URL(fileURLWithPath: path))
                    } catch {
                        print("Failed to create directory at path: \(path) due to error: \(error)")
                    }
                } catch {
                    print("Error converting video path to data: \(error)")

                }
                
                Task {
                    let (msg, err) = await gosnMessage.sendVideoMessage(self.conversation.targetId, path)
                    await MainActor.run {
                        if err == nil {
                            MHAlert.dismiss()
                            self.updateTableView(msg!)
                        }else{
                            MHAlert.showMessage(KLocalizedString("发送失败"))
                        }
                    }
                }
                
//                let password = getRandString(withLength: 8)
//                let videoContent = gosnMessage.makeVideoMessage(outputPath!, "", password)
//                //videoContent.duration = Int(round(Double(time.value) / Double(time.timescale)))
//                videoContent.duration = Int(asset!.duration)
//                self.sendFile(contnet: videoContent,pwd: password)
//                MHAlert.showMessage(KLocalizedString("AlertSendLoading"))
//                self.sendMessage(content: videoContent, pwd: password)
            } failure: { errStr, err in
                
            }

            
            
//            TZImageManager.default()!.getVideoOutputPath(with: asset) { [weak self] outputPath in
//
//                let password = getRandString(withLength: 8)
//                let videoContent = gosnMessage.makeVideoMessage(outputPath!, "", password)
//                videoContent.duration = Int(round(Double(time!.value) / Double(time!.timescale)))
//                self.sendFile(contnet: videoContent,pwd: password)
//                MHAlert.showMessage(KLocalizedString("AlertSendLoading"))
//                self.sendMessage(content: videoContent, pwd: password)
//
////                let videoContent = OsnVideoMessageContent(path: outputPath, thumbnail: coverImage!)
////                videoContent!.duration = Int(asset!.duration)
////                        MHAlert.showMessage(KLocalizedString("AlertSendLoading"))
////                self!.sendMessage(content: videoContent, pwd: getRandString(withLength: 8))
//            } failure: { errorMessage, error in
//                print("Error getting video output path: \(errorMessage ?? ""), \(error?.localizedDescription ?? "")")
//            }
        }
                
        present(imagePickerVc!, animated: true, completion: nil)
    }
    
    func sendFile (contnet:OsnMessageContent,pwd:String) {
       
        fileContentUpdate(contnet, pwd: pwd)
    }
    
    
//MARK: Cell Delegate

//MARK: 工具方法
    func getKeywordWithContent(_ content: OsnMessageContent) -> OsnMessageContent {
        if let textContent = content as? OsnTextMessageContent {
            if let dic = UserDefaults.standard.dictionary(forKey: MHHYCrossImSensitiveWords),
               let sensitiveWordsArr = dic["keywordArray"] as? [String] {
                for component in sensitiveWordsArr {
                    if textContent.data.contains(component) {
                        textContent.data = maskSensitiveWordsInString(textContent.data, sensitiveWordsArr)
                    }
                }
            }
            
            return content
        } else {
            return content
        }
    }

    func maskSensitiveWordsInString(_ text: String, _ sensitiveWords: [String]) -> String {
        var maskedText = text
        for word in sensitiveWords {
            if let range = maskedText.range(of: word) {
                let replacement = String(repeating: "*", count: word.count)
                maskedText.replaceSubrange(range, with: replacement)
            }
        }
        return maskedText
    }
    
    func needShowTime(time:Int64) -> Bool{
        let t = time - lastDateInterval
        msgShowTimeCount += 1
        if msgShowTimeCount > 10 || Int(lastDateInterval) == 0 || t > 200000 {
            lastDateInterval = time
            msgShowTimeCount = 0
            return true
        }
        return false
    }
    
//MARK: 界面交互

    // 长按图标通知点击处理
    func longIconNoticeToClick(at index: Int) {
//        guard let msg = dataSource[index] else { return }
//        if let userInfo = DMCCIMService.getInstance()?.getUserInfo((msg as! MessageInfo).target) {
//            upLongArray.append(userInfo.userId)
//            sendNoticeArray = upLongArray
//            let alias = userInfo.getAlias()
//            sendView.textView.text = "\(sendView.getTextFieldContent())@\(alias) "
//            sendView.textView.becomeFirstResponder()
//        }
    }

    // 弹出语音视图
    func loadAudioView() {
        if haveAVAuthorizationStatusCode() {
            view.endEditing(true)
            cellHeight(height: 300)
            audioView.isHidden = false
        }
    }

    // 控制弹出视图高度
    func loadEmjView() {
        view.endEditing(true)
        cellHeight(height: 300)
        emoView.isHidden = false
    }
    
    // 控制more视图高度
    func loadMoreView() {
        let height = 300
        cellHeight(height: CGFloat(height))
        moreView.isHidden = false
    }

    // 恢复弹出视图高度
    func recoverEmjView() {
//        tableView.frame.origin.y = isMulSelect == true ? GKNavHeight : 0
        emoView.isHidden = true
        sendView.emojViewNormal()
    }

    // 恢复more视图高度
    func recoverMoreView() {
//        tableView.frame.origin.y = isMulSelect ? GKNavHeight : 0
        moreView.isHidden = true
        self.sendView.morejViewNomal()
    }
    
    func recovereAudioView () {
        self.audioView.isHidden = true;
//        cellHeight(height: CGFloat(300))
        self.sendView.audioViewNormal()
    }

    // 恢复输入框bar高度
    func recoverSendView() {
        UIView.animate(withDuration: 0.25) {
            self.tableView.frame.origin.y = 0
            self.sendView.snp.updateConstraints { make in
                make.bottom.equalTo(self.view.snp.bottom).offset(-iPhoneXBottomHeight)
            }
            
//            self.tableView.contentInset = UIEdgeInsets(top: self.tableView.contentInset.top, left: 0, bottom: 60, right: 0)
        }
    }
    
    // 恢复所有视图
    func recoverAllView() {
        view.endEditing(true)
        recoverEmjView()
        recoverMoreView()
        recoverSendView()
        recovereAudioView()
    }

    // ScrollView 开始拖拽
    override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
//        view.endEditing(true)

        if conversation.type != .Service {
            recoverAllView()
        }
    }

    // 重新加载表格并滚动到底部
    func tableviewRedloadWithBottom() {

        guard self.dataSource.count > 0 else {
            return
        }

        let index = NSIndexPath(row: self.dataSource.count - 1, section: 0)
        let cell = self.tableView.cellForRow(at: index as IndexPath)
        if cell != nil {
            self.tableView.scrollToRow(at: index as IndexPath, at: .bottom, animated: true)
        }else{
            self.tableView.reloadData()
        }

    }

    // 控制键盘弹出时，聊天消息弹出的问题
    func cellHeight(height: CGFloat) {
        tableviewRedloadWithBottom()
        let visibleCells = self.tableView.visibleCells.compactMap { $0 as? BaseChatCell }
        var mHeight: CGFloat = 0
        
        for cell in visibleCells {
            let msg = cell.message
            if let content = msg.content as? OsnCallMessageContent, content.action == 0 {
                continue
            }
            
            let nickNameHeight = group.showAlias ? 20 : 0
            let msgTimeHeight = msg.showTime ? 20 : 0
            let digestHeight = 0 // = msg.extra == nil ? 0 : msg.msgDigestHeight
            
            mHeight += CGFloat(msg.msgCellHeight == 0 ? (40 + nickNameHeight + msgTimeHeight + digestHeight) : (msg.msgCellHeight + nickNameHeight + msgTimeHeight + digestHeight))
        }
        

        

        

        
        var tableH: CGFloat = 0
        let sendHeight = sendView.frame.size.height
        let tabH = tableView.mj_h
        let tabH2 = self.tableView.frame.size.height
//        let sendViewY = sendView.mj_y
        let centerHeight = kScreenHeight - height - sendHeight - GKNavHeight - 20  //tableView.frame.size.height - sendView.mj_y //UIScreen.main.bounds.height - height - sendHeight - GKNavHeight
        
        if mHeight > self.tableView.frame.size.height  - height  + sendHeight {
            mHeight = self.tableView.frame.size.height  - height + sendHeight + iPhoneXNavStatus + 20 //kScreenHeight - height - sendHeight - 50
        }
//        if mHeight > tableView.frame.size.height - sendHeight  {
//            mHeight = CGFloat(Int(tableView.frame.size.height - sendHeight ))
//        }

        if mHeight < centerHeight {
            tableH = 0
        } else {
            tableH = mHeight - centerHeight  //Double(mHeight) - centerHeight
        }

        view.needsUpdateConstraints()
        UIView.animate(withDuration: 0.25) {
            self.tableView.frame.origin.y = -tableH
            self.sendView.snp.updateConstraints { make in
                make.bottom.equalTo(self.view.snp.bottom).offset(-height)
            }
            self.sendView.superview?.layoutIfNeeded()
        }
        
//        tableView.contentInset = UIEdgeInsets(top: tableView.contentInset.top, left: 0, bottom: 60, right: 0)
    }

    // 刷新表格偏移量
    func refreshTableviewY(height: CGFloat) {
//        tableView.contentInset = UIEdgeInsets(top: tableView.contentInset.top, left: 0, bottom: 60, right: 0)
        let visibleCells = tableView.visibleCells.compactMap { $0 as? BaseChatCell }
        var mHeight: CGFloat = 0
        
        for cell in visibleCells {
//            let cell = cell as! BaseChatCell
            let msg = cell.message
//            if let content = msg.content as? OsnCallMessageContent, content.action == 0 {
//                continue
//            }
            
            let nickNameHeight = group.showAlias  ? 20 : 0
            let msgTimeHeight = msg.showTime ? 20 : 0
            let digestHeight = 0 //= msg.extra.isEmpty ? 0 : msg.msgDigestHeight
            
            mHeight += CGFloat(msg.msgCellHeight == 0 ? (40 + nickNameHeight + msgTimeHeight + digestHeight) : (msg.msgCellHeight + nickNameHeight + msgTimeHeight + digestHeight))
        }
        
        var tableH: CGFloat = 0
        let sendHeight = sendView.frame.size.height
        let centerHeight = kScreenHeight - height - sendHeight - GKNavHeight   //tableView.frame.size.height - sendView.mj_y //UIScreen.main.bounds.height - height - sendHeight - GKNavHeight
        
        if mHeight > self.tableView.frame.size.height  - height  + sendHeight {
            mHeight = self.tableView.frame.size.height  - height + sendHeight + iPhoneXNavStatus + 20  //kScreenHeight - height - sendHeight - 50
        }
        
        if mHeight < centerHeight {
            tableH = 0
        } else {
            tableH = mHeight - centerHeight //Double(mHeight) - centerHeight
        }
        
        self.tableView.frame.origin.y = -tableH
    }


    // 关闭键盘
    func closeKeyboard() {
        if keyHeight > 0 {
            recoverAllView()
        }
    }
    
    func goSearchMsg() {
        var index = 0
        for (i, msg) in dataSource.enumerated() {
            let message = msg as! DMCCMessage
            if message.msgHash == searchMsg!.msgHash {
                index = i
            }
        }
        if index != 0 {
            let indexPath = IndexPath(row: index, section: 0)
            tableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
        }
    }

    
    //MARK: Emo表情 更多 Block
    func emoSendBlock () {
        let sendStr = self.sendView.getTextFieldContent()
        if  sendStr.isEmpty  {
         MHAlert.showMessage(KLocalizedString("AlertNoSendNullMsg"))
         return
        }
        if sendStr.count > 2000 {
            MHAlert.showMessage(KLocalizedString("AlertSendMoreWordNum"))
            return
        }
        
        let msg = gosnMessage.makeTextMessage(sendStr)//OsnTextMessageContent(sendStr)
        self.sendMessage(content: msg, pwd: "")
    }
    
    func emoClickBlock (str:String) {
        sendView.setEmojText(str)
    }
    
    func moreSendBlock (index:Int) {
        switch index {
        case 0: //发图片
            sendImage()
        case 1: //拍摄
            let camera = ZLCustomCamera()
            camera.takeDoneBlock = { [weak self] image, videoUrl in
                guard let self = self else {return}
                MHAlert.showLoading()
                if (image != nil) {
                    
                    let uuid = UUID().uuidString
                    let cacheDir = cachePath(of: self.conversation, mediaType: .image)
                    // 构建图片路径
                    let path = "\(cacheDir)/img\(uuid).jpg"
                    
//                    let password = getRandString(withLength: 8)
                    
                    // 构建图片路径
    
                    let data = image!.jpegData(compressionQuality: 1)! as Data
    
                    do {
                        try data.write(to: URL(fileURLWithPath: path))
                    } catch {
                        print("Failed to create directory at path: \(path) due to error: \(error)")
                    }
  
                    Task {
                        let (msg, err) = await gosnMessage.sendImageMessage(self.conversation.targetId, path)
                        await MainActor.run {
                            if err == nil {
                                MHAlert.dismiss()
                                self.updateTableView(msg!)
                            }else{
                                MHAlert.showMessage(KLocalizedString("发送失败"))
                            }
                        }
                    }

                }else if (videoUrl != nil) {
                    let cacheDir = cachePath(of: self.conversation, mediaType: .video)
                    // 构建图片路径
                    let path = "\(cacheDir)/veido\(OsnUtils.getTimeStamp()).mp4"
                    do {
                        let data = try Data(contentsOf: videoUrl!)
                        
                        do {
                            try data.write(to: URL(fileURLWithPath: path))
                        } catch {
                            print("Failed to create directory at path: \(String(describing: path)) due to error: \(error)")
                        }
                    } catch {
                        print("Error converting video path to data: \(error)")

                    }
                    
                    Task {
                        let (msg, err) = await gosnMessage.sendVideoMessage(self.conversation.targetId, path)
                        await MainActor.run {
                            if err == nil {
                                MHAlert.dismiss()
                                self.updateTableView(msg!)
                            }else{
                                MHAlert.showMessage(KLocalizedString("发送失败"))
                            }
                        }
                    }
                   
                }
            }
            showDetailViewController(camera, sender: nil)
        case 2: //名片
           
            if chatType == 0 {
                self.presentVC(VC: ShareUserVC(curentUser: user, curentGroup: DMCCGroup()))
            }else{
                self.presentVC(VC: ShareUserVC(curentUser: DMCCUser(), curentGroup: group))
            }
        case 3://文件
            self.presentVC(VC: self.documentPickerVC)
            
        default:
            break
        }
    }
    
    func audioCompletionBlock (file:String) {
        sendAudioMessage(amrPath: file)
    }

    
    
//MARK: Request 网络请求
    // 获取群公告
    func getGroupNotice() {
        guard chatType == 1 else { return }
        
        DispatchQueue.global(qos: .default).async { [weak self] in
            guard let self = self else { return }

            DispatchQueue.main.async {
                if self.group.billboard.count > 0 {
                    self.noticeView.noticeLab.text = "\(KLocalizedString("ContactGroupNotice"))：\(self.group.billboard)"
                    self.noticeView.isHidden = false
                    self.tableView.contentInset = UIEdgeInsets(top: 22, left: 0, bottom: 60, right: 0)
                } else {
                    self.noticeView.isHidden = true
                    self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 60, right: 0)
                }
            }
        }
        getTopMessage()
    }
    
    // 获取顶部消息
    func getTopMessage() {
        DispatchQueue.global(qos: .default).async { [weak self] in
            guard let self = self else { return }
//            let array = group.getTopMessages()
            
            DispatchQueue.main.async {
                let isNotice = self.noticeView.isHidden
                
//                if !array.isEmpty {
//                    self.topHeadView.isHidden = false
//                    self.topHeadView.dataSource = array
//                    self.tableView.contentInset = UIEdgeInsets(top: isNotice ? 64 : 32 + 64,
//                                                              left: 0,
//                                                              bottom: self.sendView.frame.size.height,
//                                                              right: 0)
//                } else {
//                    self.topHeadView.isHidden = true
                    self.tableView.contentInset = UIEdgeInsets(top: isNotice ? 0 : 32,
                                                              left: 0,
                                                              bottom: 0,
                                                              right: 0)
//                }
                
//                self.checkShowDapp()
            }
        }
    }
    
//MARK: Table
    // 表格视图节的数量
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    // 每个节的行数
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }

        // 表格视图单元格配置
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell = BaseChatCell()
//            let info = dataSource[indexPath.row]
        guard let msg = dataSource[indexPath.row] as? DMCCMessage else {
            return UITableViewCell()
        }
        
        if msg.content is OsnTextMessageContent {
            if msg.getFrom() == myInfo.userId {
                cell = tableView.dequeueReusableCell(withIdentifier: "TextCellMe", for: indexPath) as! TextCell
            }else{
                cell = tableView.dequeueReusableCell(withIdentifier: "TextCell", for: indexPath) as! TextCell
            }
        } else if msg.content is OsnImageMessageContent || msg.content is OsnStickerMessageContent {
            if msg.getFrom() == myInfo.userId {
                cell = tableView.dequeueReusableCell(withIdentifier: "ImageCellMe", for: indexPath) as! ImageCell
            }else{
                cell = tableView.dequeueReusableCell(withIdentifier: "ImageCell", for: indexPath) as! ImageCell
            }
        } else if msg.content is OsnVoiceMessageContent {
            if msg.getFrom() == myInfo.userId {
                cell = tableView.dequeueReusableCell(withIdentifier: "VoiceCellMe", for: indexPath) as! VoiceCell
            }else{
                cell = tableView.dequeueReusableCell(withIdentifier: "VoiceCell", for: indexPath) as! VoiceCell
            }
        } else if msg.content is OsnCardMessageContent {
            if msg.getFrom() == myInfo.userId {
                cell = tableView.dequeueReusableCell(withIdentifier: "CardCellMe", for: indexPath) as! CardCell
            }else{
                cell = tableView.dequeueReusableCell(withIdentifier: "CardCell", for: indexPath) as! CardCell
            }
        } else if msg.content is OsnVideoMessageContent {
            if msg.getFrom() == myInfo.userId {
                cell = tableView.dequeueReusableCell(withIdentifier: "VedioCellMe", for: indexPath) as! VedioCell
            }else{
                cell = tableView.dequeueReusableCell(withIdentifier: "VedioCell", for: indexPath) as! VedioCell
            }
        } else if msg.content is OsnFileMessageContent {
            if msg.getFrom() == myInfo.userId {
                cell = tableView.dequeueReusableCell(withIdentifier: "FileCellMe", for: indexPath) as! FileCell
            }else{
                cell = tableView.dequeueReusableCell(withIdentifier: "FileCell", for: indexPath) as! FileCell
            }
        } else if msg.content is OsnNotifyContent {
            cell = tableView.dequeueReusableCell(withIdentifier: "SystemCell", for: indexPath) as! SystemCell
        } else {
            cell = tableView.dequeueReusableCell(withIdentifier: "SystemCell", for: indexPath) as! SystemCell
        }
        
        cell.isMulSelect = isMulSelect
        cell.setChatType(chatType, myInfo: myInfo, userInfo: user, withConversation: conversation)
        msg.groupInfo = group
        cell.setMessage(msg)
        cell.delegate = self
        cell.indexPath = indexPath
        return cell
    }

    // 表格视图选择事件
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        let msg = dataSource[indexPath.row] as! DMCCMessage
        if msg.content is OsnCallMessageContent {
            let callContent = msg.content as! OsnCallMessageContent
            if callContent.status.isEmpty {
                return 0
            }
        }
        var type = msg.msgType
        
//        if msg.content is OsnNotifyContent {
//            type = .unknown
//        }
        if type.rawValue >= 10 {
            type = .unknown 
        }

        let cellCls = cellContentDict[String(type.rawValue)] as! BaseChatCell
        cellCls.baseCellHeight(message: msg, chatType: chatType == 1 ? false : true, mulSelect: isMulSelect, isMySend: msg.getFrom() == self.myInfo.userId)
        let nickNameHeight = group.showAlias ? 20 : 2 // 假设昵称高度为22，根据实际情况调整
        let msgTimeHeight = msg.showTime ? 20 : 0
        
        let isExtra = (msg.extra.count > 0) ? true : false
        let digestHeight = isExtra ?msg.msgDigestHeight : 0
        
        if msg.msgCellHeight == 0 {
            return CGFloat(nickNameHeight + msgTimeHeight + digestHeight)
        } else {
            return CGFloat(msg.msgCellHeight + nickNameHeight + msgTimeHeight + digestHeight)
        }
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 0.001
    }
    
    // MARK: - Cell Delegate
    func cellTapBlock(indexPath: IndexPath) {
        tapClick(indexPath: indexPath)
    }
    
    func cellLongBlock(indexPath: IndexPath) {
        print("[FW]:\(indexPath.row)")
//        let cell = getCell(index: indexPath.row)
        
        let msg = self.dataSource[indexPath.row] as? DMCCMessage
        
        let manager = PopMenuManager()
//        PopMenuManager.default
//        manager.actions.removeAll()
        let shareItem = PopMenuDefaultAction(title: "复制", image: UIImage(named: "copy"), didSelect: { action in
            let content = msg!.content as? OsnTextMessageContent
            UIPasteboard.general.string = content?.data ?? ""
            MHAlert.showMessage("已复制到剪贴板")
        })
        
        let relayItem = PopMenuDefaultAction(title: "转发", image: UIImage(named: "forwrod"), didSelect: { [weak self] action in
            guard let self = self else {return}
            let vc = ShareVC(type: .chat)
//            vc.delegate = self
            vc.msg = msg!
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: DispatchWorkItem(block: {
                self.presentVC(VC: vc)
            }))
            
        })
        
        let delItem = PopMenuDefaultAction(title: "删除", image: UIImage(named: "del"), didSelect: { action in
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: DispatchWorkItem(block: {
                MHAlert.showSheetAlert("是否删除该条消息？") { ac in
                    if ac.title == KLocalizedString("Sure") {
                        if gosnMessage.delOneMessage(msg!.msgHash) {
                            self.dataSource.remove(at: indexPath.row)
                            self.tableView.reloadData()
                        }else {
                            MHAlert.showMessage("删除失败")
                        }
                    }
                }
            }))
        })
        
        if msg?.msgType == .text {
            manager.addAction(shareItem)
        }
        
        manager.addAction(relayItem)
        manager.addAction(delItem)
        manager.present()
    }
    
    func cellCloseKeyBlock(indexPath: IndexPath) {
        
    }
    
    func cellErrorTapBlock(indexPath: IndexPath) {
        
    }
    
    func cellIconTapBlock(indexPath: IndexPath) {
        let message = dataSource[indexPath.row] as! DMCCMessage
        if message.direction == .Send {
                self.navigationController?.pushViewController(MySetVC(), animated: true)
                return
        }
//        let userInfo = message.originalUser.isEmpty ? nil : (gosnUser.getUserInfo(message.originalUser, inGroup: con?.targetId ?? "", refresh: false)!)
            var userInfo: DMCCUser?
            if message.getFrom() == myInfo.userId {
                userInfo = gosnUser.getUserInfoDefault(myInfo.userId)
            } else if message.originalUser.count > 0 {
                userInfo = gosnUser.getUserInfoDefault(message.originalUser)
            } else {
                userInfo = gosnUser.getUserInfoDefault(message.target)
            }

            guard let userInfo = userInfo else { return } // 如果userInfo为nil，可以返回一个默认的cell或者处理错误

        if gosnFriend.isFriend(userInfo.userId) || message.getFrom() == myInfo.userId {
                let detailViewController = UserDetailVC(userInfo: userInfo)
                navigationController?.pushViewController(detailViewController, animated: true)
            } else {
                let addFriendViewController = AddUserVC(userInfo: userInfo)
                navigationController?.pushViewController(addFriendViewController, animated: true)
        }
    }
    
    func cellMulSelectBlock(indexPath: IndexPath) {
        
    }
    
    func cellLongIconBlock(indexPath: IndexPath) {
        
    }
    
    // MARK: - 处理 Cell 事件
    func                                                                               tapClick (indexPath:IndexPath) {
        guard let msg = dataSource[indexPath.row] as? DMCCMessage else { return }

                if msg.content is OsnVideoMessageContent || msg.content is OsnImageMessageContent {
                    openImageOrVideo(obj: msg, indexPath: indexPath)
                } else if msg.content is OsnCardMessageContent {
                    if let cardContent = msg.content as? OsnCardMessageContent {
                        switch cardContent.cardType {
                        case "user":
                            let userInfo = gosnUser.getUserInfoDefault(cardContent.target)//DMCCUser(null: cardContent.targetId)
                            if userInfo.userId == gosnUser.myId(){
                                
                            }else if gosnFriend.isFriend(userInfo.userId) {
                                let detailVC = UserDetailVC(userInfo: userInfo)
                                navigationController?.pushViewController(detailVC, animated: true)
                            } else {
                                let addFriendVC = AddUserVC(userInfo: userInfo)
                                navigationController?.pushViewController(addFriendVC, animated: true)
                            }
                            break
                            
                        case "group":
                            let conv = gosnConversation.getConversationInfo(cardContent.target)//DMCCConversation(param: cardContent.targetId, type: 1)
                            
                            if conv != nil {
                                let singleChatVC = ChatVC(conversation: conv!)
                                navigationController?.pushViewController(singleChatVC, animated: true)
                            }else {
                                let groupInfo =  gosnGroup.getGroupInfoDefault(cardContent.target)//(cardContent.target)//DMCCGroup(null: cardContent.targetId)
                                let addGroupVC = AddGroupVC(group: groupInfo)
                                navigationController?.pushViewController(addGroupVC, animated: true)
                            }

                            break
                        case "litapp":
                            let dic = cardContent.toJson()
                            let litapp = gosnDapp.fromJson(dic)//DMCCDapp(card: cardContent)
//                            let dappVC = WebVC(appInfo: litapp, dismissCompletion: {
////                                guard let self = self else {return}
////                                self.recoverAllView()
//                            }
//                            let navVC = YLNavigationVC(rootViewController: dappVC)
//                            self.presentVC(VC: navVC)
                           self.presentVC(VC: YLNavigationVC(rootViewController: WebVC(appInfo: litapp, dismissCompletion: { [weak self] in
                                                               guard let self = self else {return}
                                                               self.recoverAllView()
                                                           })))
                            
                            
                            break

                        default:
                            break
                        }
                    }
                } else if msg.content is OsnVoiceMessageContent {
                    playSoundWithMsg(msg, withIndex: indexPath.row)
 
                } else if msg.content is OsnFileMessageContent {
                    downFileWithMsg(with: msg)
                }
    }
    
    func getCell (index:Int) -> BaseChatCell {
//        let cell = tableView(tableView, cellForRowAt: IndexPath(row: index, section: 0)) as! BaseChatCell
        let cell = self.tableView.cellForRow(at: IndexPath(row: index, section: 0) as IndexPath) as! BaseChatCell
        return cell
    }
     
    //下载或打开文件
    func downFileWithMsg(with message: DMCCMessage) {
        guard let fileContent = message.content as? OsnFileMessageContent else { return }

        if fileContent.remoteUrl.hasSuffix(".zip") && fileContent.decKey.count == 0 {
            MHAlert.showMessage(KLocalizedString("FileError"))
            return
        }

        
//        vc.fileName = fileContent.name
        if (fileContent.localPath.count > 0) {
//            if message.target == gosnUser.myId() {
            self.navigationController?.pushViewController(FileVC(withUrl: fileContent.localPath,fileName: fileContent.name), animated: true)
//            }else{
//                previewFileWithURL(url: URL(fileURLWithPath: fileContent.localPath))
//            }
        }else if fileContent.remoteUrl.hasSuffix(".zip") && !fileContent.decKey.isEmpty {
            self.downFile(message)
            return
        } else {
            self.navigationController?.pushViewController(FileVC(withUrl: fileContent.remoteUrl,fileName: fileContent.name), animated: true)
        }
    }
    
    func downFile(_ obj: DMCCMessage) {
        
        MHAlert.showLoading()
        
        
        Task{
            let res = await gosnMessage.decodeMedia(obj)//(content!.remoteUrl, getRandString(withLength: 8), OsnUploadType.temp)
            await MainActor.run {
                if res {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                        let index = self.messageIndex(for: obj.msgHash)
                        MHAlert.dismiss()
                        let newMsg = gosnMessage.getMessageFromHash(obj.msgHash)! as DMCCMessage
                        self.dataSource[index] = newMsg
                        let indexPath = IndexPath(row: index, section: 0)
                        self.tableView.reloadRows(at: [indexPath], with: .automatic)
                        self.downFileWithMsg(with: newMsg)
                    }
                }else{
                    MHAlert.showMessage(KLocalizedString("GroupMessageTimeOut"))
                }
            }
        }
    }
    
//    func previewFileWithURL(url:URL) {
//        if url.isFileURL {
//            var str = getHomeFilePath(localPath: url.absoluteString)
//            if str.hasPrefix("file://") {
//                str = str.replacingOccurrences(of: "file://", with: "")
//            }
//            
//            if FileManager.default.fileExists(atPath: str) {
//                self.doVC = UIDocumentInteractionController(url: url)
//                doVC?.delegate = self
//                doVC?.presentOpenInMenu(from: self.view.bounds, in: view, animated: true)
//            }
//        }else{
//             // true
//            let res = url.scheme?.contains("http")
//            if res! {
//                // 获取文档目录路径
//                guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
//                    print("无法获取文档目录")
//                    return
//                }
//
//                // 拼接文件路径
//                let filePath = documentsDirectory.appendingPathComponent(url.lastPathComponent)
//                
//                let session = URLSession.shared
//                let request = URLRequest(url: url)
//                let downloadTask = session.downloadTask(with: request,
//                       completionHandler: { (location:URL?, response:URLResponse?, error:Error?)
//                        -> Void in
//                    self.doVC = UIDocumentInteractionController(url: url)
//                    self.doVC?.delegate = self
//                    self.doVC?.presentOpenInMenu(from: self.view.bounds, in: self.view, animated: true)
//                    })
//                downloadTask.resume()
//
//            }
//        }
//    }
    
    // 查看图片或视频
    func openImageOrVideo(obj: DMCCMessage,indexPath:IndexPath) {
        view.endEditing(true)
        
        let content = obj.content as? OsnMediaMessageContext
        
        if content!.remoteUrl.hasSuffix(".zip") && content!.decKey.isEmpty {
            MHAlert.showMessage(KLocalizedString("FileError"))
            return
        }
        
        if content?.localPath.count == 0 {
            downImageOrVideo(obj: obj)
            return
        }
        
        let homeDirectoryURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first
        var homeStr = homeDirectoryURL?.path
        
        homeStr = formatLocalUrl(filePath: homeStr!)
        content!.localPath = getHomeFilePath(localPath: content!.localPath)
//        var datas: [YBIBDataProtocol] = []
        
        var datas: [Any] = []
        
        if content!.decKey.isEmpty && obj.direction == .Receive{
            datas.append(URL(string: content!.remoteUrl) as Any)
        }else{
            datas.append(URL(fileURLWithPath: content!.localPath))
        }
        
       
//            datas.append(UIImage(named: "launchBg"))
        
        let videoSuffixs = ["mp4", "mov", "avi", "rmvb", "rm", "flv", "3gp", "wmv", "vob", "dat", "m4v", "f4v", "mkv"] // and more suffixs
        let vc = ZLImagePreviewController(datas: datas, index: 0, showSelectBtn: false) { url -> ZLURLType in
            if let sf = url.absoluteString.split(separator: ".").last, videoSuffixs.contains(String(sf)) {
                return .video
            } else {
                return .image
            }
        } urlImageLoader: { url, imageView, progress, loadFinish in
            imageView.kf.setImage(with: url) { receivedSize, totalSize in
                let percentage = (CGFloat(receivedSize) / CGFloat(totalSize))
                debugPrint("\(percentage)")
                progress(percentage)
            } completionHandler: { _ in
                loadFinish()
            }
        }
        
        vc.doneBlock = { datas in
            debugPrint(datas)
        }

        vc.modalPresentationStyle = .fullScreen
        showDetailViewController(vc, sender: nil)
//        presentVC(VC: vc)
        
//        if obj.content is OsnImageMessageContent {
//            
//            let imgContent = obj.content as! OsnImageMessageContent
//            
//            imgContent.localPath = getHomeFilePath(localPath: imgContent.localPath)
//            
//
//            if !imgContent.localPath.isEmpty {
//                let data =  YBIBImageData()
//                var imgStr = String()
//                if imgContent.localPath.contains(homeStr!) {
//                    if imgContent.localPath.hasSuffix(".jpg") {
//                        imgStr = imgContent.localPath
//                    } else if imgContent.localPath.hasSuffix(".png") {
//                        imgStr = imgContent.localPath
//                    } else {
//                        imgStr = imgContent.localPath
//                    }
//                    data.imagePath = imgStr
//                    datas.append(data)
//                } else {
//                    
//                    if imgContent.localPath.hasPrefix("/var/mobile/Media/") {
//                        imgStr = imgContent.localPath
//                        data.imageURL = URL(fileURLWithPath: imgContent.localPath)
//                        datas.append(data)
//                    }else if imgContent.localPath.hasSuffix(".png") || imgContent.localPath.hasSuffix(".jpg") {
//                        imgStr = imgContent.localPath
//                        data.imagePath = imgStr
//                        datas.append(data)
//                    }else{
//                        imgStr = imgContent.remoteUrl
//                        data.imageURL = URL(string: imgStr)
//                        datas.append(data)
//                        downImageOrVideo(obj: obj)
//                        return
//                    }
//                }
//            } else {
//                let data =  YBIBImageData()
//                var imgStr = String()
//                if imgContent.remoteUrl.hasSuffix(".jpg") {
//                    imgStr = imgContent.remoteUrl
//                } else if imgContent.remoteUrl.hasSuffix(".png") {
//                    imgStr = imgContent.localPath
//                } else {
//                    imgStr = imgContent.remoteUrl
//                }
//
//                data.imageURL = URL(string: imgStr)
//                datas.append(data)
//                
//                downImageOrVideo(obj: obj)
//                return
//                
//            }
//        } else if obj.content is OsnVideoMessageContent {
//            let videoContent = obj.content as! OsnVideoMessageContent
//            videoContent.localPath = getHomeFilePath(localPath: videoContent.localPath)
//            if videoContent.remoteUrl.hasSuffix(".zip") && videoContent.decKey.isEmpty {
//                MHAlert.showMessage(KLocalizedString("FileError"))
//                return
//            }
//            if !videoContent.localPath.isEmpty {
//                let data =  YBIBVideoData()
//                var videoStr = String()
//                if videoContent.localPath.contains(homeStr!) {
//                    if videoContent.localPath.hasSuffix(".mp4") {
//                        videoStr = videoContent.localPath
//                    } else {
//                        videoStr = videoContent.localPath
//                    }
//                    data.videoURL = URL(fileURLWithPath: videoStr)
//                } else if videoContent.localPath.hasSuffix(".mp4") {
//                    videoStr = videoContent.localPath
//                    data.videoURL = URL(fileURLWithPath: videoStr)
//                } else {
//                    videoStr = videoContent.remoteUrl
//                    downImageOrVideo(obj: obj)
//                    return
//                }
////                data.videoURL = URL(string: videoStr)
//                datas.append(data)
//            } else {
//                let data =  YBIBVideoData()
//                var videoStr = String()
//                videoStr = videoContent.remoteUrl
//
//                data.videoURL = URL(string: videoStr)
//                datas.append(data)
//                downImageOrVideo(obj: obj)
//                return
//                
//            }
//        }
        
//        if !datas.isEmpty {
//            let browser = YBImageBrowser()
//            browser.dataSourceArray = datas
//            browser.currentPage = 0
//            browser.defaultToolViewHandler!.topView.operationType = .save
//            browser.show()
//        }
    }
    
    
    // 下载图片或视频
        func downImageOrVideo(obj: DMCCMessage) {
            
            MHAlert.showLoading()
            let content = obj.content as? OsnMediaMessageContext
            
            if (content?.remoteUrl.count)! > 0  {
                Task{
                    let res = await gosnMessage.decodeMedia(obj)//(content!.remoteUrl, getRandString(withLength: 8), OsnUploadType.temp)
                    await MainActor.run {
                        if res {
                            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
//                                let message = msg as! DMCCMessage
                                
                                let index = self.messageIndex(for: obj.msgHash)
                                if index >= 0 {
                                    MHAlert.dismiss()
                                    
                                    let updatedMessage = gosnMessage.getMessageFromHash(obj.msgHash)//DMCCIMService.getInstance().queryMessage(obj.msgHash)
                                    
                                    self.dataSource[index] = updatedMessage as Any
                                    
                                    let indexPath = IndexPath(row: index, section: 0)
                                    self.tableView.reloadRows(at: [indexPath], with: .automatic)
                                    
                                    self.openImageOrVideo(obj: gosnMessage.getMessageFromHash(obj.msgHash)!,indexPath: IndexPath(row: index, section: 0))
                                }
                            }
                        }else{
                            MHAlert.showMessage(KLocalizedString("GroupMessageTimeOut"))
                        }
                    }
                }
            }else{
                MHAlert.showMessage(KLocalizedString("url 为空"))
            }
        }
    
    func messageIndex(for msgHash: String) -> Int {
        for (index, message) in dataSource.enumerated() {
            if (message as! DMCCMessage).msgHash == msgHash {
                return index
            }
        }
        return -1
    }
    
    // 播放语音
    func playSoundWithMsg(_ msg: DMCCMessage, withIndex index: Int) {
        guard let soundContent = msg.content as? OsnVoiceMessageContent else {
            return
        }
        
        if soundContent.remoteUrl.hasSuffix(".zip") && soundContent.decKey.isEmpty {
            MHAlert.showMessage(KLocalizedString("FileError"))
            return
        }
        
        if !soundContent.localPath.isEmpty {
            
            var voiceStr = String()
            let locStr = soundContent.localPath
            if soundContent.localPath.hasSuffix(".mp3") {
                voiceStr = locStr
            }else{
                voiceStr = "\(locStr)"
            }
            
            AudioPlayer.share().playAudio(withURLString: voiceStr, at: UInt(index))
            AudioPlayer.share().delegate = self
        } else if soundContent.remoteUrl.hasSuffix(".zip") && !soundContent.decKey.isEmpty {
            self.downSound(msg)
            return
        } else {
            let soundStr = soundContent.remoteUrl.hasSuffix(".mp3") ? soundContent.remoteUrl : soundContent.remoteUrl
            AudioPlayer.share().playAudioOnline(withContentsOf: URL(string: soundStr)!)
            AudioPlayer.share().delegate = self
        }
        
        if msg.status == .Unread {
            if gosnMessage.updateMessageStatus(msg.msgHash, .Readed) {
                msg.status = .Readed
            }
            
//            osnMessage.  未完成  补一下更新message status 状态
            
//            if DMCCIMService.getInstance().updateMessageStatus(msg.msgHash, status: Message_Status_Readed) {
////                    updateMessageStatus(msg.msgHash, status: MessageStatus.Read) {
//                msg.status = Message_Status_Readed
//            }
            
            let idx = self.messageIndex(for: msg.msgHash)
            if idx != -1 {
                self.dataSource[idx] = gosnMessage.getMessageFromHash(msg.msgHash)! as DMCCMessage
                let indexPath = IndexPath(row: idx, section: 0)
                tableView.reloadRows(at: [indexPath], with: .automatic)
            }
        }
    }
    
    // 下载音频文件
        func downSound(_ obj: DMCCMessage) {
            
            MHAlert.showLoading()
            let content = obj.content as? OsnVoiceMessageContent
            
            if (content?.remoteUrl.count)! > 0  {
                Task{
                    let res = await gosnMessage.decodeMedia(obj)//(content!.remoteUrl, getRandString(withLength: 8), OsnUploadType.temp)
                    await MainActor.run {
                        if res {
                            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                                let index = self.messageIndex(for: obj.msgHash)
                                MHAlert.dismiss()
                                self.dataSource[index] = gosnMessage.getMessageFromHash(obj.msgHash)! as DMCCMessage
                                let indexPath = IndexPath(row: index, section: 0)
                                self.tableView.reloadRows(at: [indexPath], with: .automatic)
                                self.playSoundWithMsg(gosnMessage.getMessageFromHash(obj.msgHash)!, withIndex: index)
                            }
                        }else{
                            MHAlert.showMessage(KLocalizedString("GroupMessageTimeOut"))
                        }
                    }
                }
            }else{
                MHAlert.showMessage(KLocalizedString("url 为空"))
            }

        }
    
    func audioPlayerStateDidChanged(_ audioPlayerState: AudioPlayerState, for index: UInt) {

        let msg = self.dataSource[Int(index)] as! DMCCMessage
                
        for cell in self.tableView.visibleCells {
            guard let chatCell = cell as? VoiceCell,
                  msg.msgHash == chatCell.message.msgHash else {
                continue
            }
            
            if audioPlayerState.rawValue == 2 {
                chatCell.voiceImg.startAnimating()
            } else if audioPlayerState.rawValue == 0 || audioPlayerState.rawValue == 3 {
                chatCell.voiceImg.stopAnimating()
            }
        }
//        if audioPlayerState.rawValue == 2 || audioPlayerState.rawValue == 0 {
//
//        }
    }
    
    // MARK: - SendView 输入框 Delegate
    func didReturn(str: String) {
        let sendStr = str.replacingOccurrences(of: "'", with: "’")
        let set = CharacterSet.whitespacesAndNewlines
        // 从字符串中过滤掉首尾的空格和换行, 得到一个新的字符串
        let nStr = sendStr.trimmingCharacters(in: set)

        if sendStr.isEmpty || nStr.isEmpty {
            if sendStr.isEmpty {
                MHAlert.showMessage(KLocalizedString("AlertNoSendNullMsg"))
            }
            return
        }

        if sendStr.count > 2000 {
            MHAlert.showMessage(KLocalizedString("AlertSendMoreWordNum"))
            return
        }

        let msg = OsnTextMessageContent()
        msg.data = sendStr //self.wordfilter.filter(sendStr)

        if !self.sendNoticeArray.isEmpty {
            msg.mentionedType = .targets
            msg.mentionedTargets = self.sendNoticeArray
        }

        if self.replyMsg != nil {
//            let contnet = 
//            let quote = gosnMessage.withQuoteInfo(<#T##content: OsnMessageContent##OsnMessageContent#>, self.replyMsg)
//            quote.messageHash = self.replyMsg!.msgHash
//            quote.userId = self.replyMsg!.target
//            let userInfo = gosnUser.getUserInfo(self.replyMsg!.target)
//            quote.userDisplayName = userInfo!.getAlias()
//            quote.messageDigest = self.replyMsg!.digest()
//            quote.messageHasho = self.replyMsg!.msgHasho
//            msg.quoteInfo = quote
        }

        self.sendView.replyView.isHidden = true
        self.sendView.textViewTopConstraint.constant = 10
//        self.sendView.updateConstraints {
//            $0.height.offset(75)
//            $0.width.offset(kScreenwidth)
//            $0.bottom.equalTo(self.view).offset(-self.keyHeight)
//        }
//        self.sendView.layoutIfNeeded()

        self.sendMessage(content: msg, pwd: "")
    }
    
    func didEmoView(isSelect: Bool) {
        recoverMoreView()
        recovereAudioView()
        if (isSelect) {
//            self.view.endEditing(true)
            loadEmjView()
        } else {
            recoverEmjView()
            sendView.textView.becomeFirstResponder()
        }
    }
    
    func didVoiceBtn() {
        loadAudioView()
    }
    
    func didMoreBtn(isSelect: Bool) {
        if(isSelect) {
            self.view.endEditing(true)
            recoverEmjView()
            recovereAudioView()
            loadMoreView()
        }else{
            recoverMoreView()
            sendView.textView.becomeFirstResponder()
        }
    }
    
    func didVoiceBtnSelect(isSelect: Bool) {
        recoverEmjView()
        recoverMoreView()
        if isSelect {
            loadAudioView()
            
        } else {
            recovereAudioView()
            sendView.textView.becomeFirstResponder()
        }
    }
    
    func didClearReply() {
        
    }
    
    func didKeyHeight(height: Float) {
        
    }
    
    func didNoticeToBlock() {
        
    }
    // MARK: - 分享Delegate
    func shareSelectInfos(targetId: String) {
        
    }
    // MARK: - 通知
    // 接收消息时调用的方法
    func onReceiveMessages(msg: DMCCMessage) {
        

        gosnConversation.clearUnread(conversation.targetId)
//        let messages = notification.object as? [DMCCMessage]
//        
//        let msg = messages?.first!
        
        if  msg.direction == .Send {
            return
        }
        
        if msg.target == conversation.targetId  {
//            messages!.forEach { message in
//                if let content = message.content as? OsnCallMessageContent,
//                   content.duration != -1 {
//                    dataSource.append(message)
//                } else {
            msg.showTime = needShowTime(time: msg.timestamp)
            dataSource.append(msg)
//                }
//            }
            
            GK_main_async_safe { [weak self] in
                guard let self = self else {return}

                if self.dataSource.isEmpty {
                    return
                }
                
                self.tableView.reloadData()
                if isRefrash {
                    let index = IndexPath(row: dataSource.count - 1, section: 0)
                    tableView.scrollToRow(at: index, at: .bottom, animated: false)
                }
            }
        }
        
        // 处理禁言
//            if msg!.content is GroupInfoMemberAllowNotificationContent {
//                groupUpdata()
//            } else if msg!.content is GroupInfoMemberAllowNotificationContent {
//                groupUpdata()
//            }
    }
    
    // 判断是否禁言
    func groupUpdata() {
        DispatchQueue.global(qos: .default).async {
            guard let gm = gosnMember.getMemberInfo(self.conversation.targetId, gosnUser.myId()) else {
                return
            }
            let group = self.group
            
            DispatchQueue.main.async {
                if group.singleMute == 1 {
                    self.sendView.muteViewHidden(false)
                    return
                }

                if (gm.mute != 0) && gm.type == .Normal {
                    self.sendView.muteViewHidden(false)
                } else if (group.mute != 0) && gm.type == .Normal {
                    self.sendView.muteViewHidden(false)
                } else {
                    self.sendView.muteViewHidden(true)
                }
            }
        }
    }
        
    @objc func onGroupRefreshChanged() {
        updateGroup()
        tableView.reloadData()
    }
    
    // 当消息列表改变时调用的方法
    @objc func onMessageListChanged(notification: Notification) {
        if notification.object as? DMCCConversation === conversation {
            dataSource.removeAll()
            tableView.reloadData()
        }
    }

    // 当群组信息更新时调用的方法
    func groupInfoUpdated(group: DMCCGroup) {
        if group.groupId == group.groupId {
//            getTopMessage()
        }
    }
    
    @objc func kAddChatMessage(notification: Notification) {
        if notification.object is DMCCMessage{
            let msg = notification.object as! DMCCMessage
            dataSource.append(msg)
            tableView.reloadData()
        }
    }


    
    //点击通知栏
    func noticeBlock () {
//        guard let group = DMCCIMService.getInstance()?.getGroupInfo(conversation!.targetId, refresh: false) else { return }
//        let vc = MHHYSettingContactVC.init(with: group, type: 3)
//        vc.confirmBlock = { contactArray in
//            var upArray = [String]()
//            var nameArray = [String]()
//            for mem in contactArray {
//                upArray.append(mem.memberId)
//                if let user = DMCCIMService.getInstance()?.getUserInfo(mem.memberId, inGroup: mem.groupId, refresh: false) {
//                    nameArray.append(user.getAlias())
//                }
//            }
//            self.sendNoticeArray = upArray
//            self.sendView.textView.text = "\(self.sendView.getTextFieldContent())@\([nameArray.joined(separator: "@")]) "
//        }
//        navigationController?.pushViewController(vc, animated: true)
    }
    
    @objc  func reloadMessage () {
          self.dataSource.removeAll()
          self.isOneceLoad = 0
          self.isLoadMore = 0
          self.loadDBMessage()
    }
    
    // 键盘即将出现
    @objc func keyboardWillAppearance(_ notification: Notification) {
        guard let userInfo = notification.userInfo,
//              let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval,
              let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else {
            return
        }
        
        let height = keyboardFrame.size.height
        keyHeight = Float(height)
        if height == 0 {
            return
        }
        
        cellHeight(height: height)
    }
    
    // 键盘即将消失
    @objc func keyboardWillDismiss(_ notification: Notification) {
        keyHeight = 0
    }

    // MARK: - 初始化
    
    func setup () {
        
        let head = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(loadMoreData))
        head.lastUpdatedTimeLabel?.isHidden = true
        head.stateLabel?.isHidden = true
        self.tableView.mj_header = head
        tableView.backgroundColor = kGrayBG
        
        tableStytle = .grouped
        self.view.backgroundColor = UIColor.white
        
        if self.isShowFooter {
            let footer = MJRefreshAutoFooter(refreshingTarget: self, refreshingAction: #selector(loadMoreFooterData))
            self.tableView.mj_footer = footer
        }
        
        tableView.register(UINib(nibName: "TextCell", bundle: nil), forCellReuseIdentifier: "TextCell")
        tableView.register(UINib(nibName: "TextCellMe", bundle: nil), forCellReuseIdentifier: "TextCellMe")
        registerCell(cell: TextCell(), content: OsnTextMessageContent() as Any)
        
        tableView.register(UINib(nibName: "ImageCell", bundle: nil), forCellReuseIdentifier: "ImageCell")
        tableView.register(UINib(nibName: "ImageCellMe", bundle: nil), forCellReuseIdentifier: "ImageCellMe")
        registerCell(cell: ImageCell(), content: OsnImageMessageContent() as Any)
        
        tableView.register(UINib(nibName: "FileCell", bundle: nil), forCellReuseIdentifier: "FileCell")
        tableView.register(UINib(nibName: "FileCellMe", bundle: nil), forCellReuseIdentifier: "FileCellMe")
        registerCell(cell: FileCell(), content: OsnFileMessageContent() as Any)
        
        tableView.register(UINib(nibName: "CardCell", bundle: nil), forCellReuseIdentifier: "CardCell")
        tableView.register(UINib(nibName: "CardCellMe", bundle: nil), forCellReuseIdentifier: "CardCellMe")
        registerCell(cell: CardCell(), content: OsnCardMessageContent() as Any)
        
        tableView.register(UINib(nibName: "VoiceCell", bundle: nil), forCellReuseIdentifier: "VoiceCell")
        tableView.register(UINib(nibName: "VoiceCellMe", bundle: nil), forCellReuseIdentifier: "VoiceCellMe")
        registerCell(cell: VoiceCell(), content: OsnVoiceMessageContent() as Any)
        
        tableView.register(UINib(nibName: "VedioCell", bundle: nil), forCellReuseIdentifier: "VedioCell")
        tableView.register(UINib(nibName: "VedioCellMe", bundle: nil), forCellReuseIdentifier: "VedioCellMe")
        registerCell(cell: VedioCell(), content: OsnVideoMessageContent() as Any)
        
        tableView.register(UINib(nibName: "SystemCell", bundle: nil), forCellReuseIdentifier: "SystemCell")
        registerCell(cell: SystemCell(), content: OsnNotifyContent() as Any)
        
        // 假设 self.tableView 是一个 UITableView 的实例
        self.tableView.separatorStyle = .none // 设置 TableView 的分割线样式为无
        self.tableView.reloadData() // 重新加载 TableView 的数据

        if self.conversation.type == .Service {
            // 对于服务消息不做处理
            sendView.isHidden = true
        } else {
            // 添加 sendView 为 view 的子视图
            self.view.addSubview(self.sendView)
            
            self.sendView.snp.makeConstraints { make in
                make.height.equalTo(60)
                make.width.equalTo(kScreenWidth)
                make.bottom.equalTo(self.view.snp.bottom).offset(-iPhoneXBottomHeight)
            }
        }
        
        self.navigationItem.rightBarButtonItem = self.rt_customBackItemWithTarget(self, action: #selector(pushDetailVC), image: "nav_more")

        // 设置 TableView 的 contentInset
        self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 60 + tabBarHeight, right: 0)
        self.tableView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight - iPhoneXBottomHeight)
    }
    
    @objc func pushDetailVC () {
        if chatType == 0 {
            navigationController?.pushViewController(SingleDetailVC(userInfo: user, con: conversation), animated: true)
        }else{
            navigationController?.pushViewController(GroupDetailVC(group: group, con: conversation), animated: true)
        }
        
    }
    
    override func loadMoreData () {
        isOneceLoad = 1
        self.loadDBMessage()
    }
    

    
    private lazy var documentPickerVC: UIDocumentPickerViewController = {
//            let types: [String] = [
//                "com.microsoft.powerpoint.ppt",
//                "com.microsoft.word.doc",
//                "org.openxmlformats.wordprocessingml.document",
//                "org.openxmlformats.presentationml.presentation",
//                "public.mpeg-4",
//                "com.adobe.pdf",
//                "public.mp3",
//                "public.text",
//                "public.plain-text",
//                "public.image",
//                "public.movie",
//                "public.content",
//                "com.pkware.zip-archive"
//            ]
        
//        let types: [String] = ["public.content",
//                             "public.text",
//                             "public.source-code",
//                             "public.image",
//                             "public.audiovisual-content",
//                             "com.adobe.pdf",
//                             "com.apple.keynote.key",
//                             "com.microsoft.word.doc",
//                             "com.microsoft.excel.xls",
//                             "com.microsoft.powerpoint.ppt"]
        
        let types: [String] = [String(kUTTypePDF), String(kUTTypePlainText),String(kUTTypeImage),String(kUTTypeMP3),String(kUTTypeVideo)]
            
        let documentPickerVC = UIDocumentPickerViewController(documentTypes: types, in: .open)
            documentPickerVC.delegate = self
//            documentPickerVC.navigationBar.tintColor = UIColor.white
            documentPickerVC.modalPresentationStyle = .formSheet
            
            return documentPickerVC
        }()
    
//    public static func downloadFile(WithDocumentUrl url: URL, completion: ((Data) -> Void)? = nil) {
//            let document = SxsDocument.init(fileURL: url)
//            document.open { (success) in
//                if success {
//                    document.close(completionHandler: nil)
//                }
//                if let callback = completion {
//                    callback(document.data)
//                }
//            }
//        }
    
    func copyFile(from sourcePath: String, to destinationPath: String) -> String {
        let fileManager = FileManager.default
        do {
            try fileManager.copyItem(atPath: sourcePath, toPath: destinationPath)
            return ""
        } catch {
            print("Error copying file: \(error)")
            return error.localizedDescription
        }
    }
    
    // MARK: - UIDocumentInteractionControllerDelegate Methods

    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        return self
    }

    func documentInteractionControllerViewForPreview(_ controller: UIDocumentInteractionController) -> UIView? {
        return self.view
    }

    func documentInteractionControllerRectForPreview(_ controller: UIDocumentInteractionController) -> CGRect {
        let previewHeight: CGFloat = 300
        return CGRect(x: 0, y: self.view.frame.size.height - previewHeight, width: self.view.frame.size.width, height: previewHeight)
    }
    
    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        
        
        guard let firstURL = urls.first else { return }
        let auth = urls.first?.startAccessingSecurityScopedResource()
        
        if auth! {
            let fileCoordinator = NSFileCoordinator()
            var error: NSError?
            fileCoordinator.coordinate(readingItemAt: firstURL, options: [], error: &error) { newURL in
//                var filePath = newURL.absoluteString
                let fileName = newURL.lastPathComponent

                let documentsPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
                let uuid = UUID().uuidString + "\(OsnUtils.getTimeStamp())"
                let file = "\(documentsPath)/\(uuid)"

                
                let fff = newURL.path
//                let res = FileManager.default.fileExists(atPath: fff)
                let res = copyFile(from: fff, to: file)
                
                if res == "" {
                    
//                    let originalString = fileName
//                    let fuck = originalString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
                    // 将String转换为Data
  
                    
//                    let newURL = URL(fileURLWithPath: file).deletingLastPathComponent().appendingPathComponent(fuck!)
////                    var file2 = "\(file)/nihao"
//                    do {
//                        try FileManager.default.moveItem(at: URL(fileURLWithPath: file), to: newURL)
//                        print("文件名更改成功！")
//                    } catch {
//                        print("文件名更改失败：\(error)")
//                    }
                    MHAlert.showLoading()
                    Task {
                        let (msg, err) = await gosnMessage.sendFileMessage(self.conversation.targetId, file,fileName)
                        await MainActor.run {
                            if err == nil {
                                MHAlert.dismiss()
                                self.updateTableView(msg!)
                            }else{
                                MHAlert.showMessage(KLocalizedString("发送失败"))
                            }
                        }
                    }
                }else {
                    GK_main_async_safe {
                        MHAlert.showMessage(KLocalizedString(res))
                    }
                }
            }

        }
        
        
    }
    
    func registerCell(cell:Any,content:Any) {
        let con = content as! OsnMessageContent
        cellContentDict.setObject(cell, forKey: String(con.contentType.rawValue) as NSCopying)
    }
    
    func updateGroup () {
        guard let groupInfo = gosnGroup.getGroupInfo(group.groupId) else {
            return
        }
        self.group = groupInfo
    }

    lazy var group : DMCCGroup = {
        return gosnGroup.getGroupInfoDefault(self.conversation.targetId)
    }()
    
    lazy var user : DMCCUser = {
        return gosnUser.getUserInfoDefault(self.conversation.targetId)
    }()
    
    func registerNotification () {
        // 添加观察者监听特定的通知
        
        geventService.addObserver(OsnEvent.ReceiveMessages, "ReceiveMessages_ChatVC") { [weak self] data in
            guard let self = self else {return}

            let msg = data as? DMCCMessage
            self.onReceiveMessages(msg: msg!)

        }
        
        geventService.addObserver(OsnEvent.RecallMessages, "RecallMessages_ChatVC") { [weak self] data in
            guard let self = self else {return}
            self.reloadMessage()
        }

        
        geventService.addObserver(OsnEvent.DeleteMessages, "DeleteMessages_ChatVC") { [weak self] data in
            guard let self = self else {return}
            self.reloadMessage()
        }

        
        geventService.addObserver(OsnEvent.GroupMemberUpdated, "GroupMemberUpdated_ChatVC") { [weak self] data in
            guard let self = self else {return}
            self.groupUpdata()
        }

        
        geventService.addObserver(OsnEvent.GroupInfoUpdated, "GroupInfoUpdated_ChatVC") { [weak self] data in
            guard let self = self else {return}
            let group = data as? DMCCGroup
            self.reloadMessage()
            self.groupInfoUpdated(group: group!)
        }

        geventService.addObserver(OsnEvent.GroupMute, "GroupMute_ChatVC") { [weak self] data in
            guard let self = self else {return}
            self.reloadMessage()
        }
        
        
//        NotificationCenter.default.addObserver(self, selector: #selector(onReceiveMessages), name: NSNotification.Name(rawValue: OsnEvent.ReceiveMessages.rawValue), object: nil)
        

        NotificationCenter.default.addObserver(self, selector: #selector(onGroupRefreshChanged), name: NSNotification.Name(rawValue: kGroupUpdateChanged), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(kAddChatMessage), name: NSNotification.Name(rawValue: kUpdateChatMessage), object: nil)

//        NotificationCenter.default.addObserver(self, selector: #selector(reloadMessage), name: NSNotification.Name(rawValue: OsnEvent.RecallMessages.rawValue), object: nil)
//        NotificationCenter.default.addObserver(self, selector: #selector(reloadMessage), name: NSNotification.Name(rawValue: OsnEvent.DeleteMessages.rawValue), object: nil)
//        NotificationCenter.default.addObserver(self, selector: #selector(groupUpdata), name: NSNotification.Name(rawValue: OsnEvent.GroupMemberUpdated.rawValue), object: nil)
//        NotificationCenter.default.addObserver(self, selector: #selector(groupInfoUpdated), name: NSNotification.Name(rawValue: OsnEvent.GroupInfoUpdated.rawValue), object: nil)
    }
    
    deinit {
        
        geventService.removeObserver(OsnEvent.ReceiveMessages, "ReceiveMessages_ChatVC")
        geventService.removeObserver(OsnEvent.RecallMessages, "RecallMessages_ChatVC")
        geventService.removeObserver(OsnEvent.DeleteMessages, "DeleteMessages_ChatVC")
        geventService.removeObserver(OsnEvent.GroupMemberUpdated, "GroupMemberUpdated_ChatVC")
        geventService.removeObserver(OsnEvent.GroupInfoUpdated, "GroupInfoUpdated_ChatVC")
        geventService.removeObserver(OsnEvent.GroupMute, "GroupMute_ChatVC")
        
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: kUpdateChatMessage), object: nil)

        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: kGroupUpdateChanged), object: nil)


//        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: kGroupUpdateChanged), object: nil)
//        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: OsnEvent.ReceiveMessages.rawValue), object: nil)
//        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: OsnEvent.RecallMessages.rawValue), object: nil)
//        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: OsnEvent.DeleteMessages.rawValue), object: nil)
//        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: OsnEvent.GroupMemberUpdated.rawValue), object: nil)
//        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: OsnEvent.GroupInfoUpdated.rawValue), object: nil)
        
    }
 }

class SxsDocument: UIDocument {
    public var data = Data.init()
    
    override func load(fromContents contents: Any, ofType typeName: String?) throws {
        self.data = contents as! Data
    }
}
